<?php

class UserService
{
    private $followModel;
    private $autoUidModel;
    private $userModel;
    private $userTagModel;
    private $userLoginModel;
    private $userMemberModel;
    private $userStatisticsModel;
    private $diaryListCacheModel;
    
    function __construct()
    {
        $this->followModel          =   new FollowModel();
        $this->autoUidModel       	=   new AutoUidModel();
        $this->userModel        	=   new UserModel();
        $this->userTagModel         = 	new UserTagModel();
        $this->userLoginModel       =   new UserLoginModel();
        $this->userMemberModel      =   new UserMemberModel();
        $this->userStatisticsModel  =   new UserStatisticsModel();
        $this->diaryListCacheModel  =   new DiaryListCacheModel();
    }

    /**
     * 获取用户聚合(缓存)信息
     * @param $uid
     * @param $host_uid
     * @return array|mixed
     */
    public function getUserInfo($uid, $host_uid)
    {
        $user = $this->getUserCacheInfo($uid, $host_uid);
        if (empty($user)) {
            $this->rebuildUserCache($uid, $host_uid);
            $user = $this->getUserCacheInfo($uid, $host_uid);
        }

        $user = $this->checkIsSelf($uid, $host_uid, $user);
        return $user;
    }

    /**
     * 初始化用户
     * @param $param
     * @return mixed
     */
    public function initUser($param)
    {
        $user = $param;

        try{
            $this->transactionBegin();

            $uid = $this->initAutoUid($user);
            if($uid){
                $user['uid'] = $uid;
                if ("粉粉用户" === $user['nickname']) $user['nickname'] .= $uid;

                $this->initUserLogin($user);
                $this->initUserInfo($user);
                $this->initUserStatistics($user);
                $this->initUserMember($user);

                if (AC::$errorNo){
                    $this->transactionRollback();
                    return false;
                }
            }

            $this->transactionCommit();
        }catch (Exception $e){
            $this->transactionRollback();
        }

        return $uid;
    }

    /**
     * 获取用户uid
     * @param $param
     * @return bool|int|resource
     */
    private function initAutoUid($param)
    {
        $uid = $this->autoUidModel->initAutoUid($param);
        if (empty($uid))
        {
            UK::varDump(AC::$errorNo, __METHOD__);
            return  FALSE;
        }

        return $uid;
    }

    /**
     * 初始化用户登陆数据
     * @param $param
     * @return bool
     */
    private function initUserLogin($param)
    {
        $result = $this->userLoginModel->initUserLogin($param);
        if (empty($result))
        {
            UK::varDump(AC::$errorNo, __METHOD__);
            return  FALSE;
        }

        return $result;
    }

    /**
     * 初始化用户信息
     * @param $param
     * @return bool|int|resource
     */
    private function initUserInfo($param)
    {
        $result = $this->userModel->registerUser($param);
        if (empty($result))
        {
            UK::varDump(AC::$errorNo, __METHOD__);
            return  FALSE;
        }

        return $result;
    }

    /**
     * 初始化用户计数
     * @param $param
     * @return bool|int|resource
     */
    private function initUserStatistics($param)
    {
        $data = array('uid' => $param['uid']);
        $result = $this->userStatisticsModel->initUserStatistics($data);
        if (empty($result))
        {
            UK::varDump(AC::$errorNo, __METHOD__);
            return  FALSE;
        }

        return $result;
    }

    /**
     * 初始化用户附属信息
     * @param $param
     * @return bool|int|resource
     */
    private function initUserMember($param)
    {
        $result = $this->userMemberModel->initUserMember($param);
        if (empty($result))
        {
            UK::varDump(AC::$errorNo, __METHOD__);
            return  FALSE;
        }

        return $result;
    }

    /**
     * 获取autouid表中的用户信息
     * @param $uid
     * @return Array
     */
    private function getAutoUidDetail($uid)
    {
        $autoUidDetail = $this->autoUidModel->getAutoUidDetail($uid);
        if (empty($autoUidDetail)) return array();

        return $autoUidDetail;
    }

    /**
     * 获取user表中的用户信息
     * @param $uid
     * @return array|bool|mixed
     */
    private function getUserDetail($uid)
    {
        $userDetail = $this->userModel->getUserInfo($uid);
        if (empty($userDetail)) return array();

        return $userDetail;
    }

    /**
     * 获取user_tag表中的用户标签信息
     * @param $uid
     * @return Ambigous|array
     */
    private function getUserTagsDetail($uid)
    {
        $userTagsDetail = $this->userTagModel->getUserAllTags($uid);
        if (empty($userTagsDetail)) return array();

        return $userTagsDetail;
    }

    /**
     * 获取userlogin表中的用户信息
     * @param $account
     * @return Array
     */
    private function getUserLoginDetail($account)
    {
        $userTagsDetail = $this->userLoginModel->getUserInfoByAccount($account);
        if (empty($userTagsDetail)) return array();

        return $userTagsDetail;
    }

    /**
     * 获取usermember表中的用户信息
     * @param $uid
     * @return array|bool|mixed
     */
    private function getUserMemberDetail($uid)
    {
        $userMemberDetail = $this->userMemberModel->getMemberInfo(array('uid' => $uid));
        if (empty($userMemberDetail)) return array();

        return $userMemberDetail;
    }

    /**
     * 获取userstatistics表中的用户信息
     * @param $uid
     * @return array|bool|mixed
     */
    public function getUserStatisticsDetail($uid)
    {
        $userStatisticsDetail = $this->userStatisticsModel->getUserStatisticsDetail($uid);
        if (empty($userStatisticsDetail)) return array();

        return $userStatisticsDetail;
    }

    /**
     * 获取用户达人/认证信息
     * @param $uid
     * @return Array
     */
    private function getUserAbilityDetail($uid)
    {
        $userAbilityDetail = $this->userModel->getUserRoles($uid);
        if (empty($userAbilityDetail)) return array();

        return $userAbilityDetail;
    }

    /**
     * 更新用户userstatistics计数
     * @param $uid
     * @param $info
     * @return bool|void
     */
    public function updateUserStatistics($uid, $info)
    {
        $data = $this->rebuildupdateUserStatisticsData($info);
        return $this->updateUserStatisticsByUid($uid, $data);
    }

    /**
     * 组装更新userStatistics数据
     * @param $info
     * @return array
     */
    private function rebuildUpdateUserStatisticsData($info)
    {
        $data   =   array();
        isset($info['diaryTimes'])          &&  $data['diaryTimes']         =   $info['diaryTimes'];
        isset($info['secretDiaryTimes'])    &&  $data['secretDiaryTimes']   =   $info['secretDiaryTimes'];
        isset($info['commentTimes'])        &&  $data['commentTimes']       =   $info['commentTimes'];
        isset($info['commentMeTimes'])      &&  $data['commentMeTimes']     =   $info['commentMeTimes'];
        isset($info['followMeTimes'])       &&  $data['followMeTimes']      =   $info['followMeTimes'];
        isset($info['meFollowTimes'])       &&  $data['meFollowTimes']      =   $info['meFollowTimes'];
        isset($info['likeTimes'])           &&  $data['likeTimes']          =   $info['likeTimes'];
        isset($info['likeMeTimes'])         &&  $data['likeMeTimes']        =   $info['likeMeTimes'];
        isset($info['shareTimes'])          &&  $data['shareTimes']         =   $info['shareTimes'];
        isset($info['shareMeTimes'])        &&  $data['shareMeTimes']       =   $info['shareMeTimes'];
        isset($info['messageTimes'])        &&  $data['messageTimes']       =   $info['messageTimes'];
        isset($info['newCommentTimes'])     &&  $data['newCommentTimes']    =   $info['newCommentTimes'];
        isset($info['newFollowTimes'])      &&  $data['newFollowTimes']     =   $info['newFollowTimes'];
        isset($info['newLikeMeTimes'])      &&  $data['newLikeMeTimes']     =   $info['newLikeMeTimes'];
        isset($info['blackMeTimes'])        &&  $data['blackMeTimes']       =   $info['blackMeTimes'];
        isset($info['meBlackTimes'])        &&  $data['meBlackTimes']       =   $info['meBlackTimes'];
        isset($info['topicTimes'])          &&  $data['topicTimes']         =   $info['topicTimes'];
        isset($info['topicFavorTimes'])     &&  $data['topicFavorTimes']    =   $info['topicFavorTimes'];
        isset($info['newTopicComment'])     &&  $data['newTopicComment']    =   $info['newTopicComment'];
        isset($info['newCommentMeTimes'])   &&  $data['newCommentMeTimes']  =   $info['newCommentMeTimes'];

        return $data;
    }

    /**
     * 更新用户计数信息
     * @param $uid
     * @param $data
     * @return bool
     */
    private function updateUserStatisticsByUid($uid, $data)
    {
        if (empty($uid) || empty($data))
        {
            return false;
        }

        $userStatistics = $this->userStatisticsModel->getStatisticsByUid($uid);
        if (empty($userStatistics)) return false;

        $data = $this->filterStatisticsData($data, $userStatistics);
        $result = $this->updateUserStatisticsOfMysqlByUid($uid, $data);
        $this->updateUserStatisticsOfCacheByUid($uid, $data);

        return $result;
    }

    /**
     * 过滤参数，保证字段不能小于0
     * @param $data
     * @param $userStatistics
     * @return mixed
     */
    private function filterStatisticsData($data, $userStatistics)
    {
        foreach ($data as $key=>$val)
        {
            if ($val < 0 && abs($userStatistics[$key]) < abs($val)) {
                $data[$key] = - abs($userStatistics[$key]);
            }
        }

        return $data;
    }

    /**
     * 更新用户计数数据库计数
     * @param $uid
     * @param $data
     * @return bool
     */
    private function updateUserStatisticsOfMysqlByUid($uid, $data)
    {
        return $this->userStatisticsModel->updateUserStatisticsByUid($uid, $data);
    }

    /**
     * 更新用户计数缓存
     * @param $uid
     * @param $data
     */
    private function updateUserStatisticsOfCacheByUid($uid, $data)
    {
        $userCountCache = $this->diaryListCacheModel->getUserCount($uid);
        if ($userCountCache)
        {
            $this->diaryListCacheModel->addUserCount($uid, $data);
        }
    }

    /**
     * 组装返回用户缓存信息
     * @param $uid
     * @param $host_uid
     * @return array
     */
    private function getUserCacheInfo($uid, $host_uid)
    {
        if (empty($uid)) return array();

        $userCache = $this->diaryListCacheModel->getUserCache($uid);
        if (empty($userCache)) return array();

        $user = $this->getDefaultUserStruct();
        $user['ability_level']  =   $userCache['ability_level'] ? strval($userCache['ability_level']) : '0';
        $user['account']        =   strval($userCache['account']);
        $user['avatar']         =   UK::getuseravatarurl($uid, $userCache['avatar']);
        $user['background']     =   UK::getUserBackground($uid, $userCache['background']);
        $user['email']          =   strval($userCache['email']);
        $user['gag_time']       =   $userCache['gag_time'] ? intval($userCache['gag_time']) : 0;
        $user['is_ability']     =   $userCache['is_ability'] ? '1' : '0';
        $user['is_followme']    =   0;
        $user['is_mefollow']    =   $this->checkIsFollow($uid, $host_uid);
        $user['vip_expire']     =   isset($userCache['vip_expire']) ? $userCache['vip_expire'] : '0';
        $user['is_vip']         =   $user['vip_expire']>AC::SERVER_TIME ? '1' : '0';
        $this->autoUidModel->judgeVip($user, $uid);
        $user['level']          =   strval($userCache['level']);
        $user['max_numbers']    =   $this->maxWordLength($user['is_ability']);
        $user['nickname']       =   strlen($userCache['nickname']) > 0 ? UK::getstr($userCache['nickname'], 24, '', 1) : strval($uid);
        $user['sex']            =   $this->compatibleSexOfLastVersion($userCache['sex']);
        $user['signature']      =   UK::getstr($userCache['signature'], 100, '', 1);
        $user['status']         =   strval($userCache['status']);
        $user['tag_list']       =   $this->getUserTagList($userCache['tags']);
        $user['thirdParty']     =   array('gotype_token' => $this->getGoTypePwd($uid));
        $user['uid']            =   strval($uid);
        $user['verified']       =   $userCache['verified'] ? strval($userCache['verified']) : '0';
        //订阅号作者认证等级
        $user['subscribe_level'] = !empty($user['verified']) ? 202 : 0;

        $user['nickname']       =   $this->getUserRemark($uid, $user['nickname'], $host_uid);
        return $user;
    }

    private function rebuildUserCache($uid, $host_uid)
    {
        $userInfo       = $this->getUserDetail($uid);
        if (empty($userInfo)){
            return false;
        }

        $userMemberInfo = $this->getUserMemberDetail($uid);
        $autoUidInfo    = $this->getAutoUidDetail($uid);
        $abilityInfo    = $this->getUserAbilityDetail($uid);
        $gagInfo        = $this->diaryListCacheModel->getGagUserCahce($uid);

        $user           = $this->getDefaultUserCacheStruct();
        $user['uid']            =   strval($uid);
        $user['nickname']       =   $userInfo['nickname'];
        $user['signature']      =   $userInfo['signature'];
        $user['avatar']         =   $userInfo['avatar'];
        $user['background']     =   $userInfo['background'];
        $user['level']          =   $userMemberInfo['level'] ? strval($userMemberInfo['level']) : '1';
        $user['gag_time']       =   intval($gagInfo['gag_time']);
        $user['is_ability']     =   $abilityInfo['status'] ? strval($abilityInfo['status']) : '0';
        $user['ability_level']  =   $abilityInfo['medal_id'] ? strval($abilityInfo['medal_id']) : '0';
        $user['verified']       =   $abilityInfo['verified'] ? strval($abilityInfo['verified']) : '0';
        $user['account']        =   $userInfo['account'] ? strval($userInfo['account']) : '';
        $user['tags']           =   $userInfo['tags']   ? strval($userInfo['tags']) : '';
        $user['email']          =   $userInfo['email'] ? strval($userInfo['email']) : '';
        $user['status']         =   $autoUidInfo['status'] ? strval($autoUidInfo['status']) : '0';
        $user['sex']	        =	isset($userInfo['sex']) ? $userInfo['sex']: '0';
        $user['update_time']    =   AC::SERVER_TIME;
        $user['vip_expire']    =   isset($userInfo['vip']) ? $userInfo['vip'] : '0';

        // 重建缓存
        $this->diaryListCacheModel->addUserCache($user);
        return $user;
    }

    public function updateUserCache($uid, $data)
    {
        $user = array();
        $user['uid'] = strval($uid);
        isset($data['nickname'])      && $user['nickname']       =  $data['nickname'];
        isset($data['signature'])     && $user['signature']      =  $data['signature'];
        isset($data['avatar'])        && $user['avatar']         =  $data['avatar'];
        isset($data['background'])    && $user['background']     =  $data['background'];
        isset($data['level'])         && $user['level']          =  $data['level'];
        isset($data['gag_time'])      && $user['gag_time']       =  $data['gag_time'];
        isset($data['is_ability'])    && $user['is_ability']     =  $data['is_ability'];
        isset($data['ability_level']) && $user['ability_level']  =  $data['ability_level'];
        isset($data['verified'])      && $user['verified']       =  $data['verified'];
        isset($data['tags'])          && $user['tags']           =  $data['tags'];
        isset($data['email'])         && $user['email']          =  $data['email'];
        isset($data['status'])        && $user['status']         =  $data['status'];
        isset($data['sex'])           && $user['sex']	         =	$data['sex'];
        isset($data['update_time'])   && $user['update_time']    =  $data['update_time'];
        isset($data['vip_expire'])    && $user['vip_expire']     =  $data['vip_expire'];

        // 重建缓存
        $this->diaryListCacheModel->addUserCache($user);

        return true;
    }

    private function getDefaultUserStruct()
    {
        $user = array(
            'ability_level' =>  '0',
            'account'       =>  '',
            'avatar'        =>  '',
            'background'    =>  '',
            'email'         =>  '',
            'gag_time'      =>  '0',
            'is_ability'    =>  '0',
            'is_followme'   =>  '0',
            'is_mefollow'   =>  '0',
            'is_vip'        =>  '0',
            'vip_expire'    =>  '0',
            'level'         =>  '0',
            'max_numbers'   =>  '2000',
            'nickname'      =>  '',
            'sex'           =>  '1',
            'signature'     =>  '',
            'status'        =>  '0',
            'tag_list'      =>  '',
            'thirdParty'    =>  '',
            'uid'           =>  '',
            'verified'      =>  ''
        );

        return $user;
    }

    private function getDefaultUserCacheStruct()
    {
        $user = array(
            'uid'           =>  '',
            'nickname'      =>  '',
            'signature'     =>  '',
            'avatar'        =>  '',
            'background'    =>  '',
            'level'         =>  '0',
            'gag_time'      =>  '0',
            'is_ability'    =>  '0',
            'ability_level' =>  '0',
            'verified'      =>  '',
            'account'       =>  '',
            'email'         =>  '',
            'status'        =>  '0',
            'sex'           =>  '0',
            'update_time'   =>  '',
            'vip_expire'    =>  '0'
        );
        return $user;
    }

    private function getUserTagList ($tags)
    {
        if (empty($tags)) return array();

        $tagsArr = array();
        $tag_arr = explode(',', $tags);
        foreach ($tag_arr as $val){
            $tagInfo = Tags::getTagInfo(trim($val));
            if (empty($tagInfo)){
                continue;
            }
            $tagsArr[] = $tagInfo;
        }

        return $tagsArr;
    }

    private function maxWordLength($is_ability)
    {
        $num = AC::DIARY_DATA_NUMBERS;
        if ($is_ability)
        {
            $num = AC::DIARY_DATA_NUMBERS_ABILITY;
        }
        return $num/2;
    }

    private function getGoTypePwd ($uid)
    {
        if (empty($uid)) {
            return '';
        }

        $password = md5($uid."gotye"."73g8e8xi1sse");
        return $password;
    }

    private function compatibleSexOfLastVersion($sex)
    {
        if($sex == AC::$sex['femaleauth'] && AC::$femaleVersion == 1){
            return '0';
        }
        return strval($sex);
    }

    /**
     * 获取备注信息
     * @param $uid
     * @param $nickname
     * @param $host_uid
     * @return string
     */
    public function getUserRemark($uid, $nickname, $host_uid){
        if (($uid == $host_uid) || empty($host_uid)){
            return $nickname;
        }

        $remark = $nickname;
        $friend =  $this->diaryListCacheModel->checkIsFriend($host_uid, $uid);
        if ($friend){
            $rMarkInfo = $this->diaryListCacheModel->getRmask($host_uid, $uid);
            if ($rMarkInfo) {
                $tmp = json_decode($rMarkInfo,true);
                if ($tmp['r']){
                    $remark = $tmp['r'];
                }
            }else{
                $remark = $this->rebuildRemarkCache($uid, $nickname, $host_uid);
            }
        }

        return $remark;
    }

    /**
     * 获取、重建用户备注缓存
     * @param $uid
     * @param $nickname
     * @param $host_uid
     * @return string
     */
    private function rebuildRemarkCache($uid, $nickname, $host_uid){
        $remark = $this->autoUidModel->getRemarkFromMysql($host_uid, $uid);
        if (empty($remark)) return $nickname;

        $data = json_encode(array('r'=>$remark));
        $this->diaryListCacheModel->addRmask($host_uid, $uid, $data);

        return $remark;
    }

    /**
     * 判断是否关注
     * @param $uid
     * @param $host_uid
     * @return int
     */
    private function checkIsFollow($uid, $host_uid)
    {
        if (empty($uid) || empty($host_uid) || ($uid == $host_uid)) return 0;

        if (AC::$meFollowUids === NULL){
            $follows = $this->followModel->getMeFollowsList($uid);
            if ($follows) AC::$meFollowUids = $follows;
        }

        if (in_array($host_uid, AC::$meFollowUids)){
            return 1;
        }
        return 0;
    }

    /**
     * 判断是否为当前用户
     * @param $uid
     * @param $host_uid
     * @param $user
     * @return mixed
     */
    private function checkIsSelf($uid, $host_uid, $user)
    {
        if ($uid == $host_uid || empty($user)) return $user;

        unset($user['account']);
        unset($user['email']);
        unset($user['thirdParty']);
        return $user;
    }

    /**
     * 获取用户token
     * @param $uid
     * @return Ambigous
     */
    public function getUserToken($uid)
    {
        $token = $this->diaryListCacheModel->getUserToken($uid);
        return $token;
    }

    /**
     * 检测用户禁言状态
     * @param $uid
     * @return bool
     */
    public function checkUserStatus($uid)
    {
        $user = $this->getUserInfo($uid);
        if (empty($user)) {
            return false;
        }

        return $this->autoUidModel->checkUserStatus($user);
    }

    /**
     * 检测拉黑情况
     * @param $uid
     * @param $host_uid
     * @return bool
     */
    public function checkBlackStatus($uid, $host_uid)
    {
        if ($host_uid  ==  $uid)  return  true;

        $array      =   array('uid' => $host_uid, 'fUid' => $uid, 'alarm' => TRUE);
        $isBlackMe  =   $this->followModel->isBlackMe($array);
        if (empty($isBlackMe))  return  true;

        return  false;
    }

    /**
     * 事务开启
     */
    private function transactionBegin()
    {
        $this->autoUidModel->begin();
    }

    /**
     * 事务提交
     */
    private function transactionCommit()
    {
        $this->autoUidModel->commit();
    }

    /**
     * 事务回滚
     */
    private function transactionRollback()
    {
        $this->autoUidModel->rollback();
    }

}